]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
background: don't load the same image more than once concurrently
authorRay Strode <rstrode@redhat.com>
Mon, 25 Mar 2013 19:03:48 +0000 (15:03 -0400)
committerRay Strode <rstrode@redhat.com>
Tue, 26 Mar 2013 21:02:05 +0000 (17:02 -0400)
If a background gets requested from the cache while it's still
being loaded from an earlier call, then there will be two concurrent
loads of the same file.

That concurrency is mitigates the effectiveness of the cache and
also causes leaks.

This commit consolidates file loads so that concurrency doesn't
happen.

https://bugzilla.gnome.org/show_bug.cgi?id=696157

js/ui/background.js

index cacdffb0d14c013eb47de78e85aa930d0807fca6..2625452226f2907e246661f48838c60c84b40453 100644 (file)
@@ -38,6 +38,7 @@ const BackgroundCache = new Lang.Class({
     _init: function() {
        this._patterns = [];
        this._images = [];
+       this._pendingFileLoads = [];
        this._fileMonitors = {};
     },
 
@@ -128,6 +129,73 @@ const BackgroundCache = new Lang.Class({
         this._removeContent(this._images, content);
     },
 
+    _loadImageContent: function(params) {
+        params = Params.parse(params, { monitorIndex: 0,
+                                        style: null,
+                                        filename: null,
+                                        effects: Meta.BackgroundEffects.NONE,
+                                        cancellable: null,
+                                        onFinished: null });
+
+        for (let i = 0; i < this._pendingFileLoads.length; i++) {
+            if (this._pendingFileLoads[i].filename == params.filename &&
+                this._pendingFileLoads[i].style == params.style) {
+                this._pendingFileLoads[i].callers.push({ shouldCopy: true,
+                                                         monitorIndex: params.monitorIndex,
+                                                         effects: params.effects,
+                                                         onFinished: params.onFinished });
+                return;
+            }
+        }
+
+        this._pendingFileLoads.push({ filename: params.filename,
+                                      style: params.style,
+                                      callers: [{ shouldCopy: false,
+                                                  monitorIndex: params.monitorIndex,
+                                                  effects: params.effects,
+                                                  onFinished: params.onFinished }] });
+
+        let content = new Meta.Background({ meta_screen: global.screen,
+                                            monitor: params.monitorIndex,
+                                            effects: params.effects });
+
+        content.load_file_async(params.filename,
+                                params.style,
+                                params.cancellable,
+                                Lang.bind(this,
+                                          function(object, result) {
+                                              try {
+                                                  content.load_file_finish(result);
+
+                                                  this._monitorFile(params.filename);
+                                                  this._images.push(content);
+                                              } catch(e) {
+                                                  content = null;
+                                              }
+
+                                              for (let i = 0; i < this._pendingFileLoads.length; i++) {
+                                                  let pendingLoad = this._pendingFileLoads[i];
+                                                  if (pendingLoad.filename != params.filename ||
+                                                      pendingLoad.style != params.style)
+                                                      continue;
+
+                                                  for (let j = 0; j < pendingLoad.callers.length; j++) {
+                                                      if (pendingLoad.callers[j].onFinished) {
+                                                          if (content && pendingLoad.callers[j].shouldCopy) {
+                                                              content = object.copy(pendingLoad.callers[j].monitorIndex,
+                                                                                    pendingLoad.callers[j].effects);
+
+                                                          }
+
+                                                          pendingLoad.callers[j].onFinished(content);
+                                                      }
+                                                  }
+
+                                                  this._pendingFileLoads.splice(i, 1);
+                                              }
+                                          }));
+    },
+
     getImageContent: function(params) {
         params = Params.parse(params, { monitorIndex: 0,
                                         style: null,
@@ -171,27 +239,11 @@ const BackgroundCache = new Lang.Class({
             if (params.onFinished)
                 params.onFinished(content);
         } else {
-            content = new Meta.Background({ meta_screen: global.screen,
-                                            monitor: params.monitorIndex,
-                                            effects: params.effects });
-
-            content.load_file_async(params.filename,
-                                    params.style,
-                                    params.cancellable,
-                                    Lang.bind(this,
-                                              function(object, result) {
-                                                  try {
-                                                      content.load_file_finish(result);
-
-                                                      this._monitorFile(params.filename);
-                                                      this._images.push(content);
-                                                  } catch(e) {
-                                                       content = null;
-                                                  }
+            this._loadImageContent({ filename: params.filename,
+                                     style: params.style,
+                                     cancellable: params.cancellable,
+                                     onFinished: params.onFinished });
 
-                                                  if (params.onFinished)
-                                                      params.onFinished(content);
-                                              }));
         }
     },